﻿using Simple.Framework.Ioc;
using Simple.Framework.Logger;
using Simple.Utils.Atrributes;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.BasicNet.Core.Net
 * 接口名称 MessageHandle
 * 开发人员：11920
 * 创建时间：2023/4/6 16:29:04
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.PrettyNet.Handle
{
    public class MessageHandle : IMessageHandle
    {
		protected IContainer container;

	    List<HandleLabel> handleLabels;
        protected ILogger logger;
        public MessageHandle(IContainer container)
        {
            this.container = container;
            handleLabels = new List<HandleLabel>();
            logger = container.GetService<ILogger>();
			Initalization();

        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public virtual void AnalysisHandle(Queue<DataPack> qdataPacks,byte[] data,int length)
        {
			if (data == null || length < 7)
			{
                //ReplyBuffer = ErrorReply((int)SocketErrorCode.BadRequest);

                logger.Error($"消息长度不符合要求!");
				return;
			}
            DataPack LastPack=null;
			if (qdataPacks.Count>0)
            {
                LastPack = qdataPacks.Peek();

			}
			DataPack dataPack = new DataPack();
			for (int i = 0; i < length-1; i++)
            {
				if (data[i] == 0x3E && data[i+1] == 0x24)
				{
                    if (LastPack==null||(LastPack!=null&&LastPack.Complete))
                    {
						dataPack.ReceiveBuffer = new byte[i + 2];
						dataPack.Length = i + 2;
						Array.Copy(data, 0, dataPack.ReceiveBuffer, 0, dataPack.Length);

                        SetDataPack(dataPack);
					}
					else
                    {
						byte[] buffer = new byte[length];
						Array.Copy(data, 0, buffer, 0,length);
						LastPack.ReceiveBuffer = LastPack.ReceiveBuffer.Concat(buffer).ToArray();//拼接上一次剩余的包,已经完成读取每个数据包长度
						LastPack.Length = LastPack.ReceiveBuffer.Length;
						SetDataPack(LastPack);
					}
                }
			}
		}

        /// <summary>
        /// 后续逻辑处理
        /// </summary>
        /// <param name="context"></param>
        public virtual void Handle(IContext context)
        {
            if (handleLabels.Where(label => label.IsRange(context.CurrentPack.CommandID)).Any())
            {
                var label = handleLabels.FirstOrDefault(label => label.IsRange(context.CurrentPack.CommandID));
                var handle = container.GetService(label.HandType);

                ((BaseHandle)handle).SetContext(context);
				
				foreach (var method in label.HandType.GetMethods().Where(m => m.IsDefined(typeof(MessageNumberAttribute))))
                {
                    MessageNumberAttribute NumberAttr = method.GetCustomAttribute<MessageNumberAttribute>();

                    if (NumberAttr.Number == context.CurrentPack.CommandID)
                    {
							method.Invoke(handle, new object[] { });
					}
                }
            }
            else
            {
				logger.Error($"消息号{context.CurrentPack.CommandID}不存在处理的方法,请检查!");
            }
        }

        public virtual void Handled(IContext context)
        {
			//if (context.ReceiveBuffer.Length!=length)
   //         {
			//	context.ReceiveBuffer = new byte[length-context.ReceiveBuffer.Length];
			//    Array.Copy(data,context.ReceiveBuffer.Length, context.ReceiveBuffer,0,length-context.ReceiveBuffer.Length);
   //         }
        }

        public void Initalization()
        {
            container.Register<HandleLabel>();
            #region 
            Type type = typeof(BaseHandle);
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembliy in assemblies)
            {
                foreach (var itemType in assembliy.GetTypes())
                {
                    if (itemType.IsAssignableTo(type))
                    {
                        container.Register(itemType).Autowird();
                        if (itemType.IsDefined(typeof(NumberRangeAttribute), true))
                        {

                            NumberRangeAttribute range = itemType.GetCustomAttribute<NumberRangeAttribute>();
                            var handleLabel = container.GetService<HandleLabel>();
                            handleLabel.MaxNumber = range.MaxMessageNumber;
                            handleLabel.MinNumber = range.MinMessageNumber;
                            handleLabel.HandType = itemType;
                            if (handleLabels.Where(labels => labels.IsRange(range.MinMessageNumber) || labels.IsRange(range.MaxMessageNumber)).Any())
                                throw new Exception("处理类的范围冲突,请检查,确保范围不重叠!");
                            handleLabels.Add(handleLabel);
                        }
                    }
                }
            }

            #endregion

        }

        public void SetDataPack(DataPack dataPack)
        {
			#region hader
			dataPack.HeaderBuffer = new byte[2];
			Array.Copy(dataPack.ReceiveBuffer, 0, dataPack.HeaderBuffer, 0, 2);
			#endregion

			#region tail
			dataPack.TailBuffer = new byte[2];
			Array.Copy(dataPack.ReceiveBuffer, dataPack.Length - 2, dataPack.TailBuffer, 0, 2);
			#endregion


			#region crc
			var CrcBuffer = new byte[1];
			Array.Copy(dataPack.ReceiveBuffer, dataPack.Length - 3, CrcBuffer, 0, 1);
			dataPack.CRC = Convert.ToInt32(BitConverter.ToString(CrcBuffer), 16);
			#endregion

			#region
			dataPack.CheckBuffer = new byte[dataPack.Length - 3];
			Array.Copy(dataPack.ReceiveBuffer, 0, dataPack.CheckBuffer, 0, dataPack.CheckBuffer.Length);
			#endregion


			#region pack commandID
			dataPack.CommandID = dataPack.ReceiveBuffer[3];
            #endregion

            #region extand data verify 
            dataPack.Complete = true;
			#endregion
		}

	}
}
